/*!
 * \file test_dll_helper.cpp
 * \project WonderTrader
 * 
 * \brief DLLHelper.hpp 动态库辅助工具测试用例
 * 
 * \details 测试DLLHelper类中的所有动态库操作功能：
 *          - 动态库加载和卸载
 *          - 函数符号获取和调用
 *          - 跨平台文件名处理
 *          - 异常安全的库操作
 *          
 *          注意：由于动态库加载涉及系统资源，某些测试可能需要
 *          实际的动态库文件，这里主要测试接口和错误处理
 */

#include <gtest/gtest.h>
#include <string>
#include "DLLHelper.hpp"

/*!
 * \brief DLLHelper工具测试类
 * 
 * \details 提供DLLHelper类中所有函数的全面测试，
 *          确保动态库操作的安全性和可靠性
 */
class DLLHelperTest : public ::testing::Test {
protected:
    void SetUp() override {
        // 测试前准备工作
    }

    void TearDown() override {
        // 测试后清理工作
    }
};

// ============================================================================
// 测试模块名包装功能
// ============================================================================

/*!
 * \brief 测试默认前缀的模块名包装
 */
TEST_F(DLLHelperTest, TestWrapModuleDefault) {
#ifdef _WIN32
    // Windows平台测试
    EXPECT_EQ(DLLHelper::wrap_module("test"), "test.dll");
    EXPECT_EQ(DLLHelper::wrap_module("strategy"), "strategy.dll");
    EXPECT_EQ(DLLHelper::wrap_module("parser"), "parser.dll");
    EXPECT_EQ(DLLHelper::wrap_module("trader"), "trader.dll");
    
    // 空字符串测试
    EXPECT_EQ(DLLHelper::wrap_module(""), ".dll");
    
    // 包含特殊字符的模块名
    EXPECT_EQ(DLLHelper::wrap_module("test_module"), "test_module.dll");
    EXPECT_EQ(DLLHelper::wrap_module("test-module"), "test-module.dll");
    EXPECT_EQ(DLLHelper::wrap_module("test.module"), "test.module.dll");
#else
    // Linux/Unix平台测试
    EXPECT_EQ(DLLHelper::wrap_module("test"), "libtest.so");
    EXPECT_EQ(DLLHelper::wrap_module("strategy"), "libstrategy.so");
    EXPECT_EQ(DLLHelper::wrap_module("parser"), "libparser.so");
    EXPECT_EQ(DLLHelper::wrap_module("trader"), "libtrader.so");
    
    // 空字符串测试
    EXPECT_EQ(DLLHelper::wrap_module(""), "lib.so");
    
    // 包含特殊字符的模块名
    EXPECT_EQ(DLLHelper::wrap_module("test_module"), "libtest_module.so");
    EXPECT_EQ(DLLHelper::wrap_module("test-module"), "libtest-module.so");
    EXPECT_EQ(DLLHelper::wrap_module("test.module"), "libtest.module.so");
#endif
}

/*!
 * \brief 测试自定义前缀的模块名包装
 */
TEST_F(DLLHelperTest, TestWrapModuleCustomPrefix) {
#ifdef _WIN32
    // Windows平台忽略前缀参数
    EXPECT_EQ(DLLHelper::wrap_module("test", ""), "test.dll");
    EXPECT_EQ(DLLHelper::wrap_module("test", "custom"), "test.dll");
    EXPECT_EQ(DLLHelper::wrap_module("test", "wt"), "test.dll");
#else
    // Linux/Unix平台使用自定义前缀
    EXPECT_EQ(DLLHelper::wrap_module("test", ""), "test.so");
    EXPECT_EQ(DLLHelper::wrap_module("test", "custom"), "customtest.so");
    EXPECT_EQ(DLLHelper::wrap_module("test", "wt"), "wttest.so");
    EXPECT_EQ(DLLHelper::wrap_module("test", "lib"), "libtest.so");  // 默认前缀
    
    // 空前缀测试
    EXPECT_EQ(DLLHelper::wrap_module("strategy", ""), "strategy.so");
    
    // 特殊前缀测试
    EXPECT_EQ(DLLHelper::wrap_module("parser", "my_"), "my_parser.so");
    EXPECT_EQ(DLLHelper::wrap_module("trader", "wt_"), "wt_trader.so");
#endif
}

/*!
 * \brief 测试长模块名和特殊字符
 */
TEST_F(DLLHelperTest, TestWrapModuleLongNames) {
    // 长模块名测试 - 减少长度以避免过长的错误输出
    std::string longName(50, 'a');  // 从100减少到50
    std::string expectedWindows = longName + ".dll";
    std::string expectedLinux = "lib" + longName + ".so";
    
#ifdef _WIN32
    EXPECT_EQ(DLLHelper::wrap_module(longName.c_str()), expectedWindows);
#else
    EXPECT_EQ(DLLHelper::wrap_module(longName.c_str()), expectedLinux);
#endif

    // 包含数字的模块名
#ifdef _WIN32
    EXPECT_EQ(DLLHelper::wrap_module("module123"), "module123.dll");
    EXPECT_EQ(DLLHelper::wrap_module("123module"), "123module.dll");
#else
    EXPECT_EQ(DLLHelper::wrap_module("module123"), "libmodule123.so");
    EXPECT_EQ(DLLHelper::wrap_module("123module"), "lib123module.so");
#endif
}

// ============================================================================
// 测试动态库加载功能
// ============================================================================

/*!
 * \brief 测试加载不存在的动态库
 */
TEST_F(DLLHelperTest, TestLoadNonExistentLibrary) {
    // 尝试加载不存在的库
    DllHandle handle = DLLHelper::load_library("non_existent_library.dll");
    // 如果意外成功，清理资源
    if (handle != nullptr) {
        DLLHelper::free_library(handle);
        FAIL() << "Expected nullptr for non-existent library, but got a valid handle";
    }
    EXPECT_EQ(handle, nullptr);
    
    // 尝试加载空路径
    handle = DLLHelper::load_library("");
    if (handle != nullptr) {
        DLLHelper::free_library(handle);
        FAIL() << "Expected nullptr for empty path, but got a valid handle";
    }
    EXPECT_EQ(handle, nullptr);
    
    // 尝试加载无效路径
    handle = DLLHelper::load_library("/invalid/path/to/library.so");
    if (handle != nullptr) {
        DLLHelper::free_library(handle);
        FAIL() << "Expected nullptr for invalid Unix path, but got a valid handle";
    }
    EXPECT_EQ(handle, nullptr);
    
    handle = DLLHelper::load_library("C:\\invalid\\path\\to\\library.dll");
    if (handle != nullptr) {
        DLLHelper::free_library(handle);
        FAIL() << "Expected nullptr for invalid Windows path, but got a valid handle";
    }
    EXPECT_EQ(handle, nullptr);
}

/*!
 * \brief 测试加载系统库（如果可用）
 */
TEST_F(DLLHelperTest, TestLoadSystemLibrary) {
    DllHandle handle = nullptr;
    
#ifdef _WIN32
    // Windows系统库测试
    handle = DLLHelper::load_library("kernel32.dll");
    if (handle != nullptr) {
        EXPECT_NE(handle, nullptr);
        DLLHelper::free_library(handle);
    }
    
    // 尝试加载其他常见系统库
    handle = DLLHelper::load_library("user32.dll");
    if (handle != nullptr) {
        EXPECT_NE(handle, nullptr);
        DLLHelper::free_library(handle);
    }
#else
    // Linux系统库测试
    handle = DLLHelper::load_library("libc.so.6");
    if (handle != nullptr) {
        EXPECT_NE(handle, nullptr);
        DLLHelper::free_library(handle);
    }
    
    // 尝试加载libm（数学库）
    handle = DLLHelper::load_library("libm.so.6");
    if (handle != nullptr) {
        EXPECT_NE(handle, nullptr);
        DLLHelper::free_library(handle);
    }
    
    // 尝试加载libdl（动态链接库）
    handle = DLLHelper::load_library("libdl.so.2");
    if (handle != nullptr) {
        EXPECT_NE(handle, nullptr);
        DLLHelper::free_library(handle);
    }
#endif
}

// ============================================================================
// 测试动态库释放功能
// ============================================================================

/*!
 * \brief 测试释放NULL句柄
 */
TEST_F(DLLHelperTest, TestFreeNullHandle) {
    // 释放NULL句柄应该安全
    DLLHelper::free_library(nullptr);
    
    // 多次释放NULL句柄
    DLLHelper::free_library(nullptr);
    DLLHelper::free_library(nullptr);
    
    // 这些调用不应该崩溃或产生异常
    SUCCEED();
}

/*!
 * \brief 测试重复释放句柄
 */
TEST_F(DLLHelperTest, TestDoubleFree) {
    DllHandle handle = nullptr;
    
#ifdef _WIN32
    handle = DLLHelper::load_library("kernel32.dll");
#else
    handle = DLLHelper::load_library("libc.so.6");
#endif
    
    if (handle != nullptr) {
        // 第一次释放
        DLLHelper::free_library(handle);
        
        // 第二次释放同一个句柄（这在实际使用中应该避免）
        // 注意：这可能导致未定义行为，但我们测试程序不会崩溃
        // DLLHelper::free_library(handle);  // 注释掉以避免潜在问题
        
        SUCCEED();
    }
}

// ============================================================================
// 测试符号获取功能
// ============================================================================

/*!
 * \brief 测试从NULL句柄获取符号
 */
TEST_F(DLLHelperTest, TestGetSymbolFromNullHandle) {
    // 从NULL句柄获取符号应该返回NULL
    ProcHandle proc = DLLHelper::get_symbol(nullptr, "test_function");
    EXPECT_EQ(proc, nullptr);
    
    // 测试空函数名
    proc = DLLHelper::get_symbol(nullptr, "");
    EXPECT_EQ(proc, nullptr);
    
    // 测试NULL函数名（如果支持）
    proc = DLLHelper::get_symbol(nullptr, nullptr);
    EXPECT_EQ(proc, nullptr);
}

/*!
 * \brief 测试从有效句柄获取不存在的符号
 */
TEST_F(DLLHelperTest, TestGetNonExistentSymbol) {
    DllHandle handle = nullptr;
    
#ifdef _WIN32
    handle = DLLHelper::load_library("kernel32.dll");
#else
    handle = DLLHelper::load_library("libc.so.6");
#endif
    
    if (handle != nullptr) {
        // 尝试获取不存在的符号
        ProcHandle proc = DLLHelper::get_symbol(handle, "non_existent_function");
        EXPECT_EQ(proc, nullptr);
        
        // 尝试获取空名称的符号
        proc = DLLHelper::get_symbol(handle, "");
        EXPECT_EQ(proc, nullptr);
        
        // 尝试获取无效名称的符号
        proc = DLLHelper::get_symbol(handle, "invalid@function#name");
        EXPECT_EQ(proc, nullptr);
        
        DLLHelper::free_library(handle);
    }
}

/*!
 * \brief 测试从有效句柄获取存在的符号
 */
TEST_F(DLLHelperTest, TestGetExistentSymbol) {
    DllHandle handle = nullptr;
    
#ifdef _WIN32
    handle = DLLHelper::load_library("kernel32.dll");
    if (handle != nullptr) {
        // 尝试获取Windows API函数
        ProcHandle proc = DLLHelper::get_symbol(handle, "GetCurrentProcessId");
        if (proc != nullptr) {
            EXPECT_NE(proc, nullptr);
        }
        
        // 尝试获取另一个常见函数
        proc = DLLHelper::get_symbol(handle, "GetTickCount");
        if (proc != nullptr) {
            EXPECT_NE(proc, nullptr);
        }
        
        DLLHelper::free_library(handle);
    }
#else
    handle = DLLHelper::load_library("libc.so.6");
    if (handle != nullptr) {
        // 尝试获取C标准库函数
        ProcHandle proc = DLLHelper::get_symbol(handle, "printf");
        if (proc != nullptr) {
            EXPECT_NE(proc, nullptr);
        }
        
        // 尝试获取另一个常见函数
        proc = DLLHelper::get_symbol(handle, "malloc");
        if (proc != nullptr) {
            EXPECT_NE(proc, nullptr);
        }
        
        DLLHelper::free_library(handle);
    }
#endif
}

// ============================================================================
// 测试异常安全性
// ============================================================================

/*!
 * \brief 测试异常情况下的安全性
 */
TEST_F(DLLHelperTest, TestExceptionSafety) {
    // 测试各种可能导致异常的情况
    
    // 1. 加载库时的异常安全
    DllHandle handle = DLLHelper::load_library("definitely_non_existent_library_12345.dll");
    EXPECT_EQ(handle, nullptr);
    
    // 2. 获取符号时的异常安全
    ProcHandle proc = DLLHelper::get_symbol(nullptr, "any_function");
    EXPECT_EQ(proc, nullptr);
    
    // 3. 释放库时的异常安全
    DLLHelper::free_library(nullptr);
    
    // 4. 长路径测试 - 减少长度以避免过长的错误输出
    std::string longPath(50, 'a');  // 从1000减少到50
    longPath += ".dll";
    handle = DLLHelper::load_library(longPath.c_str());
    EXPECT_EQ(handle, nullptr);
    
    // 5. 长符号名测试 - 减少长度以避免过长的错误输出
    std::string longSymbol(50, 'b');  // 从1000减少到50
    proc = DLLHelper::get_symbol(nullptr, longSymbol.c_str());
    EXPECT_EQ(proc, nullptr);
}

// ============================================================================
// 综合测试场景
// ============================================================================

/*!
 * \brief 测试完整的加载-获取符号-释放流程
 */
TEST_F(DLLHelperTest, TestCompleteWorkflow) {
    DllHandle handle = nullptr;
    
#ifdef _WIN32
    // Windows完整流程测试
    handle = DLLHelper::load_library("kernel32.dll");
    if (handle != nullptr) {
        // 获取符号
        ProcHandle proc = DLLHelper::get_symbol(handle, "GetCurrentProcessId");
        
        // 如果符号存在，验证它不为空
        if (proc != nullptr) {
            EXPECT_NE(proc, nullptr);
        }
        
        // 释放库
        DLLHelper::free_library(handle);
        
        // 释放后再次尝试获取符号应该失败（但这可能导致未定义行为）
        // proc = DLLHelper::get_symbol(handle, "GetCurrentProcessId");
        // EXPECT_EQ(proc, nullptr);  // 注释掉以避免未定义行为
    }
#else
    // Linux完整流程测试
    handle = DLLHelper::load_library("libc.so.6");
    if (handle != nullptr) {
        // 获取符号
        ProcHandle proc = DLLHelper::get_symbol(handle, "printf");
        
        // 如果符号存在，验证它不为空
        if (proc != nullptr) {
            EXPECT_NE(proc, nullptr);
        }
        
        // 释放库
        DLLHelper::free_library(handle);
    }
#endif
}

/*!
 * \brief 测试多个库的并发操作
 */
TEST_F(DLLHelperTest, TestMultipleLibraries) {
    std::vector<DllHandle> handles;
    
#ifdef _WIN32
    // 尝试加载多个Windows系统库
    std::vector<std::string> libraries = {
        "kernel32.dll",
        "user32.dll",
        "advapi32.dll"
    };
#else
    // 尝试加载多个Linux系统库
    std::vector<std::string> libraries = {
        "libc.so.6",
        "libm.so.6",
        "libdl.so.2"
    };
#endif
    
    // 加载所有库
    for (const auto& lib : libraries) {
        DllHandle handle = DLLHelper::load_library(lib.c_str());
        if (handle != nullptr) {
            handles.push_back(handle);
        }
    }
    
    // 验证加载的库数量
    EXPECT_GE(handles.size(), 0);  // 至少应该能加载0个库（系统差异）
    
    // 释放所有库
    for (auto handle : handles) {
        DLLHelper::free_library(handle);
    }
}

// ============================================================================
// 性能和压力测试
// ============================================================================

/*!
 * \brief 测试重复加载和释放的性能
 */
TEST_F(DLLHelperTest, TestRepeatedLoadUnload) {
    const int iterations = 10;  // 减少迭代次数以避免过度测试
    
#ifdef _WIN32
    const char* testLib = "kernel32.dll";
#else
    const char* testLib = "libc.so.6";
#endif
    
    for (int i = 0; i < iterations; ++i) {
        DllHandle handle = DLLHelper::load_library(testLib);
        if (handle != nullptr) {
            DLLHelper::free_library(handle);
        }
    }
    
    // 如果程序没有崩溃，测试通过
    SUCCEED();
}

/*!
 * \brief 测试模块名包装的性能
 */
TEST_F(DLLHelperTest, TestWrapModulePerformance) {
    const int iterations = 1000;
    
    for (int i = 0; i < iterations; ++i) {
        std::string moduleName = "test_module_" + std::to_string(i);
        std::string wrapped = DLLHelper::wrap_module(moduleName.c_str());
        
        // 验证结果不为空
        EXPECT_FALSE(wrapped.empty());
        
        // 验证包含正确的扩展名
#ifdef _WIN32
        EXPECT_TRUE(wrapped.find(".dll") != std::string::npos);
#else
        EXPECT_TRUE(wrapped.find(".so") != std::string::npos);
#endif
    }
} 